package com.seed.core.pojo.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.seed.core.exception.ServiceException;
import com.seed.core.pojo.dto.SeedMessageDTO;
import com.seed.core.pojo.entity.SeedBaseEntity;
import com.seed.core.pojo.manager.SeedSystemManager;
import com.seed.core.pojo.service.SeedSystemService;
import org.jeecg.common.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * @author gchiaway
 * 日期: 2020-07-20
 * 时间: 14:40
 */
public abstract class SeedSystemServiceImpl<Manager extends SeedSystemManager<Entity>, Entity extends SeedBaseEntity> extends SeedBaseServiceImpl implements SeedSystemService<Entity> {
    private final String FROM_ACTION_TOKEN_LOCK = "FROM_ACTION_TOKEN_LOCK";
    @Autowired
    protected Manager baseManager;
    protected Class<Manager> managerClass = currentManagerClass();
    protected Class<Entity> entityClass = currentModelClass();
    @Autowired
    private RedisUtil redisUtil;


    protected Class<Manager> currentManagerClass() {
        return (Class<Manager>) ReflectionKit.getSuperClassGenericType(getClass(), SeedSystemServiceImpl.class, 0);
    }

    protected Class<Entity> currentModelClass() {
        return (Class<Entity>) ReflectionKit.getSuperClassGenericType(getClass(), SeedSystemServiceImpl.class, 1);
    }

    /**
     * 获取 entity 的 class
     *
     * @return {@link Class<Entity>}
     */
    @Override
    public Class<Entity> getEntityClass() {
        return entityClass;
    }

    /**
     * 获取对应 entity 的 BaseManager
     *
     * @return BaseManager
     */
    @Override
    public SeedSystemManager<Entity> getBaseManager() {
        return baseManager;
    }

    /**
     * 校验请求令牌
     *
     * @param fromActionToken 请求令牌
     * @return 是否有效
     */
    @Override
    public Boolean checkFromActionToken(String fromActionToken) {
        if (ObjectUtils.isEmpty(fromActionToken)) {
            return false;
        }
        if (!redisUtil.hasKey(fromActionToken)) {
            return false;
        }
        synchronized (FROM_ACTION_TOKEN_LOCK) {
            if (!redisUtil.hasKey(fromActionToken)) {
                return false;
            }
            redisUtil.del(fromActionToken);
            return true;
        }
    }

    /**
     * 过滤excel数据,判断该数据是否允许导入
     *
     * @param data 单条数据
     * @return 是否允许
     */
    @Override
    public SeedMessageDTO excelDataFilter(Entity data) throws ServiceException {
        return this.checkInsertData(data);
    }

    /**
     * 校验数据,判断该数据是否允许插入
     *
     * @param data 单条数据
     * @return 是否允许
     */
    @Override
    public SeedMessageDTO checkInsertData(Entity data) throws ServiceException {
        return new SeedMessageDTO();
    }

    /**
     * 校验数据,判断该数据是否允许更新
     *
     * @param data 单条数据
     * @return 是否允许
     */
    @Override
    public SeedMessageDTO checkUpdateData(Entity data) throws ServiceException {
        return new SeedMessageDTO();
    }


    /**
     * 插入一条记录（选择字段，策略插入）
     *
     * @param entity 实体对象
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO save(Entity entity) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        SeedMessageDTO checkInsertDataDTO = this.checkInsertData(entity);
        if (!checkInsertDataDTO.getSuccess()) {
            result.setSuccess(checkInsertDataDTO.getSuccess());
            result.setCode(checkInsertDataDTO.getCode());
            result.setMessage(checkInsertDataDTO.getMessage());
            return result;
        }
        if (!baseManager.save(entity)) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("保存失败");
            return result;
        }
        result.setMessage("保存成功");
        return result;
    }

    /**
     * 批量插入
     *
     * @param entityList 实体对象集合
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO saveBatch(Collection<Entity> entityList) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        for (Entity entity : entityList) {
            SeedMessageDTO checkInsertDataDTO = this.checkInsertData(entity);
            if (!checkInsertDataDTO.getSuccess()) {
                result.setSuccess(checkInsertDataDTO.getSuccess());
                result.setCode(checkInsertDataDTO.getCode());
                result.setMessage(checkInsertDataDTO.getMessage());
                return result;
            }
        }
        if (!baseManager.saveBatch(entityList)) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("保存失败");
            return result;
        }
        result.setMessage("保存成功");
        return result;
    }

    /**
     * 插入（批量）
     *
     * @param entityList 实体对象集合
     * @param batchSize  插入批次数量
     */
    @Override
    public SeedMessageDTO saveBatch(Collection<Entity> entityList, int batchSize) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        for (Entity entity : entityList) {
            SeedMessageDTO checkInsertDataDTO = this.checkInsertData(entity);
            if (!checkInsertDataDTO.getSuccess()) {
                result.setSuccess(checkInsertDataDTO.getSuccess());
                result.setCode(checkInsertDataDTO.getCode());
                result.setMessage(checkInsertDataDTO.getMessage());
                return result;
            }
        }
        if (!baseManager.saveBatch(entityList, batchSize)) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("保存失败");
            return result;
        }
        result.setMessage("保存成功");
        return result;
    }

    /**
     * 批量修改插入
     *
     * @param entityList 实体对象集合
     */
    @Override
    public SeedMessageDTO saveOrUpdateBatch(Collection<Entity> entityList) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        for (Entity entity : entityList) {
            SeedMessageDTO checkInsertDataDTO;
            if (ObjectUtils.isEmpty(entity.getId())) {
                checkInsertDataDTO = this.checkInsertData(entity);
            } else {
                checkInsertDataDTO = this.checkUpdateData(entity);
            }
            if (!checkInsertDataDTO.getSuccess()) {
                result.setSuccess(checkInsertDataDTO.getSuccess());
                result.setCode(checkInsertDataDTO.getCode());
                result.setMessage(checkInsertDataDTO.getMessage());
                return result;
            }
        }
        if (!baseManager.saveOrUpdateBatch(entityList)) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("保存失败");
            return result;
        }
        result.setMessage("保存成功");
        return result;
    }

    /**
     * 批量修改插入
     *
     * @param entityList 实体对象集合
     * @param batchSize  每次的数量
     */
    @Override
    public SeedMessageDTO saveOrUpdateBatch(Collection<Entity> entityList, int batchSize) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        for (Entity entity : entityList) {
            SeedMessageDTO checkInsertDataDTO;
            if (ObjectUtils.isEmpty(entity.getId())) {
                checkInsertDataDTO = this.checkInsertData(entity);
            } else {
                checkInsertDataDTO = this.checkUpdateData(entity);
            }
            if (!checkInsertDataDTO.getSuccess()) {
                result.setSuccess(checkInsertDataDTO.getSuccess());
                result.setCode(checkInsertDataDTO.getCode());
                result.setMessage(checkInsertDataDTO.getMessage());
                return result;
            }
        }
        if (!baseManager.saveOrUpdateBatch(entityList, batchSize)) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("保存失败");
            return result;
        }
        result.setMessage("保存成功");
        return result;
    }

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     * @return 对应实体
     */
    @Override
    public Entity getById(Serializable id) throws ServiceException {
        try {
            return baseManager.getById(id);
        } catch (Exception e) {
            throw new ServiceException(e, id);
        }
    }

    /**
     * 查询（根据ID 批量查询）
     *
     * @param idList 主键ID列表
     */
    @Override
    public List<Entity> listByIds(Collection<? extends Serializable> idList) throws ServiceException {
        try {
            return baseManager.listByIds(idList);
        } catch (Exception e) {
            throw new ServiceException(e, idList);
        }
    }

    /**
     * 根据 ID 选择修改
     *
     * @param entity 实体对象
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO updateById(Entity entity) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        SeedMessageDTO checkInsertDataDTO = this.checkUpdateData(entity);
        if (!checkInsertDataDTO.getSuccess()) {
            result.setSuccess(checkInsertDataDTO.getSuccess());
            result.setCode(checkInsertDataDTO.getCode());
            result.setMessage(checkInsertDataDTO.getMessage());
            return result;
        }
        if (!baseManager.updateById(entity)) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("更新失败");
            return result;
        }
        result.setMessage("更新成功");
        return result;
    }

    /**
     * 批量修改
     *
     * @param entityList 实体对象集合
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO updateBatch(Collection<Entity> entityList) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        for (Entity entity : entityList) {
            SeedMessageDTO checkUpdateDataDTO = this.checkUpdateData(entity);
            if (!checkUpdateDataDTO.getSuccess()) {
                result.setSuccess(checkUpdateDataDTO.getSuccess());
                result.setCode(checkUpdateDataDTO.getCode());
                result.setMessage(checkUpdateDataDTO.getMessage());
                return result;
            }
        }
        if (!baseManager.updateBatchById(entityList)) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("更新失败");
            return result;
        }
        result.setMessage("更新成功");
        return result;
    }

    /**
     * 根据 UpdateWrapper 条件，更新记录 需要设置sqlset
     *
     * @param updateWrapper 实体对象封装操作类 {@link UpdateWrapper}
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO update(Wrapper<Entity> updateWrapper) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        boolean isSuccess;
        try {
            isSuccess = baseManager.update(updateWrapper);
        } catch (Exception e) {
            throw new ServiceException(e, updateWrapper);
        }
        if (!isSuccess) {
            result.setCode("A0500");
            result.setSuccess(false);
            result.setMessage("更新失败");
            return result;
        }
        result.setMessage("更新成功");
        return result;
    }

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO removeById(Serializable id) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        boolean isSuccess;
        try {
            isSuccess = baseManager.removeById(id);
        } catch (Exception e) {
            throw new ServiceException(e, id);
        }
        if (!isSuccess) {
            result.setCode("A0500");
            result.setMessage("删除失败");
            result.setSuccess(false);
            return result;
        }
        result.setMessage("删除成功");
        return result;
    }

    /**
     * 删除（根据ID 批量删除）
     *
     * @param idList 主键ID列表
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO removeByIds(Collection<? extends Serializable> idList) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        boolean isSuccess;
        try {
            isSuccess = baseManager.removeByIds(idList);
        } catch (Exception e) {
            throw new ServiceException(e, idList);
        }
        if (!isSuccess) {
            result.setCode("A0500");
            result.setMessage("删除失败");
            result.setSuccess(false);
            return result;
        }
        result.setMessage("删除成功");
        return result;
    }

    /**
     * 根据 entity 条件，删除记录
     *
     * @param queryWrapper 实体包装类 {@link QueryWrapper}
     * @return 是否成功
     */
    @Override
    public SeedMessageDTO remove(Wrapper<Entity> queryWrapper) throws ServiceException {
        SeedMessageDTO result = new SeedMessageDTO();
        boolean isSuccess;
        try {
            isSuccess = baseManager.remove(queryWrapper);
        } catch (Exception e) {
            throw new ServiceException(e, queryWrapper);
        }
        if (!isSuccess) {
            result.setCode("A0500");
            result.setMessage("删除失败");
            result.setSuccess(false);
            return result;
        }
        result.setMessage("删除成功");
        return result;
    }

    /**
     * 根据 Wrapper，查询一条记录 <br/>
     * <p>结果集，如果是多个会返回第一条</p>
     * <p>随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
     *
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     * @return 第一条记录
     */
    @Override
    public Entity getOne(Wrapper<Entity> queryWrapper) throws ServiceException {
        List<Entity> dataList = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(dataList)) {
            return null;
        }
        return dataList.get(0);
    }

    /**
     * 查询列表
     *
     * @return 实体对象
     */
    @Override
    public List<Entity> list() throws ServiceException {
        return baseManager.list();
    }

    /**
     * 查询列表
     *
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     * @return 实体对象
     */
    @Override
    public List<Entity> list(Wrapper<Entity> queryWrapper) throws ServiceException {
        List<Entity> entityList;
        try {
            entityList = baseManager.list(queryWrapper);
        } catch (Exception e) {
            throw new ServiceException(e, queryWrapper);
        }
        return entityList;
    }

    /**
     * 分页查询
     *
     * @param page 分页对象
     * @return 分页对象
     */
    @Override
    public IPage<Entity> page(IPage<Entity> page) throws ServiceException {
        return this.page(page, Wrappers.emptyWrapper());
    }

    /**
     * 分页查询
     *
     * @param page         分页对象
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     * @return 分页对象
     */
    @Override
    public IPage<Entity> page(IPage<Entity> page, Wrapper<Entity> queryWrapper) throws ServiceException {
        IPage<Entity> entityPage;
        try {
            entityPage = baseManager.page(page, queryWrapper);
        } catch (Exception e) {
            throw new ServiceException(e, queryWrapper);
        }
        return entityPage;
    }

    /**
     * 根据 Wrapper 条件，查询总记录数
     *
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     */
    @Override
    public int count(Wrapper<Entity> queryWrapper) throws ServiceException {
        try {
            return Math.toIntExact(baseManager.count(queryWrapper));
        } catch (Exception e) {
            throw new ServiceException(e, queryWrapper);
        }
    }
}
